﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.ComponentModel;
using System.Net.Http;
using System.Net;
using System.Configuration;
using TaskManager.Models.Interfaces.Services;
using TaskManager.Models.Services;
using TaskManager.Models.Exceptions;



namespace TaskManager.Controllers.Api
{
    //Базовый Api контроллер - все Api контроллеры наследуются от него, содержит в своем конструкторе
    //код для создания экземпляров сервисов. Кроме того содержит шаблоны для Http запросов с параметрами.
    public abstract class BaseApiController<T> : System.Web.Http.ApiController, INotifyPropertyChanged
    {

        protected readonly IUserService UserService;
      
        //Конструктор
        public BaseApiController()
        {
            UserService = new UserService();
        }

        //Реализация интерфейса INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }

        //Шаблоны для создания Http запросов с параметрами, которые используются в Api контроллерах.

        protected HttpResponseMessage Response;

        protected HttpResponseMessage CreateResponse<T>(Func<T> func)
        {
            try
            {
                var result = func();

                Response = Request.CreateResponse<T>(HttpStatusCode.OK, result);
            }
            catch (EntityNotFoundException ex)
            {
                Response = Request.CreateResponse(HttpStatusCode.NotFound, ex);
            }
            catch (Exception ex)
            {
                Response = Request.CreateResponse(HttpStatusCode.InternalServerError, ex);
            }

            return Response;
        }

        protected HttpResponseMessage CreateResponse<T1, T2>(Func<T1, T2> func, T1 arg)
        {
            try
            {
                var result = func(arg);

                Response = Request.CreateResponse<T2>(HttpStatusCode.OK, result);
            }
            catch (EntityNotFoundException ex)
            {
                Response = Request.CreateResponse(HttpStatusCode.NotFound, ex);
            }
            catch (Exception ex)
            {
                Response = Request.CreateResponse(HttpStatusCode.InternalServerError, ex);
            }

            return Response;
        }

        protected HttpResponseMessage CreateResponse<T1, T2, T3>(Func<T1, T2, T3> func, T1 arg1, T2 arg2)
        {
            try
            {
                var result = func(arg1, arg2);

                Response = Request.CreateResponse(HttpStatusCode.OK, result);
            }
            catch (EntityNotFoundException ex)
            {
                Response = Request.CreateResponse(HttpStatusCode.NotFound, ex.ToString());
            }
            catch (Exception ex)
            {
                Response = Request.CreateResponse(HttpStatusCode.InternalServerError, ex);
            }

            return Response;
        }

        protected HttpResponseMessage CreateResponse<T1, T2, T3, T4>(Func<T1, T2, T3, T4> func, T1 arg1, T2 arg2, T3 arg3)
        {
            try
            {
                var result = func(arg1, arg2, arg3);

                Response = Request.CreateResponse(HttpStatusCode.OK, result);
            }
            catch (EntityNotFoundException ex)
            {
                Response = Request.CreateResponse(HttpStatusCode.NotFound, ex.ToString());
            }
            catch (Exception ex)
            {
                Response = Request.CreateResponse(HttpStatusCode.InternalServerError, ex);
            }

            return Response;
        }



        protected HttpResponseMessage CreateResponse<T1, T2, T3, T4, T5>(Func<T1, T2, T3, T4, T5> func, T1 arg1, T2 arg2, T3 arg3, T4 arg4)
        {
            try
            {
                var result = func(arg1, arg2, arg3, arg4);

                Response = Request.CreateResponse(HttpStatusCode.OK, result);
            }
            catch (EntityNotFoundException ex)
            {
                Response = Request.CreateResponse(HttpStatusCode.NotFound, ex.ToString());
            }
            catch (Exception ex)
            {
                Response = Request.CreateResponse(HttpStatusCode.InternalServerError, ex);
            }

            return Response;
        }

        protected HttpResponseMessage CreateResponse(Action action)
        {
            try
            {
                action();

                Response = Request.CreateResponse(HttpStatusCode.OK);
            }
            catch (EntityNotFoundException ex)
            {
                Response = Request.CreateResponse(HttpStatusCode.NotFound, ex);
            }
            catch (Exception ex)
            {
                Response = Request.CreateResponse(HttpStatusCode.InternalServerError, ex);
            }

            return Response;
        }

        protected HttpResponseMessage CreateResponse<T>(Action<T> action, T arg)
        {
            try
            {
                action(arg);

                Response = Request.CreateResponse(HttpStatusCode.OK);
            }
            catch (EntityNotFoundException ex)
            {
                Response = Request.CreateResponse(HttpStatusCode.NotFound, ex);
            }
            catch (Exception ex)
            {
                Response = Request.CreateResponse(HttpStatusCode.InternalServerError, ex);
            }

            return Response;
        }

      

    }
}
